#include <stdio.h>
#include <math.h>
#include <time.h>
#include <stdlib.h>
#define PI 3.14159265358979323846

// 函数声明
double toRadians(double degree);
double toDegrees(double radians);
double calculateJulianDay(int year, int month, int day);
double calculateSolarNoon(double longitude, double julianDay, double timezone);
double calculateHourAngle(double latitude, double declination);
void calculateSunriseSunset(const char* cityName, double latitude, double longitude, int year, int month, int day, double timezone,int isDST, char* expectedSunrise, char* expectedSunset);

// int sun_test() {
//     double latitude = 30.25;    // 杭州的纬度
//     double longitude = 120.16;  // 杭州的经度
//     double timezone = 8.0;      // 杭州的时区 (UTC+8)

//     // 获取当前日期
//     time_t now = time(NULL);
//     struct tm *local = localtime(&now);
//     int year = local->tm_year + 1900;
//     int month = local->tm_mon + 1;
//     int day = local->tm_mday;

//     printf("date: %04d-%02d-%02d\n", year, month, day);
//     calculateSunriseSunset(latitude, longitude, year, month, day, timezone);

//     return 0;
// }

void testSunTimes(char* cityName, double latitude, double longitude, int year, int month, int day, double timezone,int isDST, char* expectedSunrise, char* expectedSunset) {
    calculateSunriseSunset(cityName,latitude, longitude, year, month, day, timezone, isDST, expectedSunrise, expectedSunset);
}

int main(int argc, char *argv[]) {
    if (argc != 11) {
        fprintf(stderr, "Usage: ./sun city latitude longitude offset year month day dst sunrise sunset\n");
        return 1;
    }
    // const char* filename = "/home/xs/Code/gw_simu/cde_2.0/os_gateway_simulator/apps/os_simu_32x/src/data.txt";
    // FILE* file = fopen(filename, "r");
    // if (!file) {
    //     fprintf(stderr, "无法打开测试数据文件: %s\n", filename);
    //     return;
    // }
    // char cityName[30];
    // double latitude, longitude, timezone;
    // int year, month, day, isDST;
    // char expectedSunrise[6], expectedSunset[6];

    // while (fscanf(file, "%s %lf %lf %lf %d %d %d %d %s %s", cityName, &latitude, &longitude, &timezone, &year, &month, &day, &isDST, expectedSunrise, expectedSunset) != EOF) {
    //     testSunTimes(cityName, latitude, longitude, year, month, day, timezone, isDST, expectedSunrise, expectedSunset);
    // }
    // fclose(file);


    char *cityName = argv[1];
    double latitude = atof(argv[2]);
    double longitude = atof(argv[3]);
    double timezone = atof(argv[4]);
    int year = atoi(argv[5]);
    int month = atoi(argv[6]);
    int day = atoi(argv[7]);
    int isDST = atoi(argv[8]);
    char *expectedSunrise = argv[9];
    char *expectedSunset = argv[10];

    // printf("City: %s\nLatitude: %.4f\nLongitude: %.4f\nOffset: %f\n", cityName, latitude, longitude, timezone);
    // printf("Date: %04d-%02d-%02d\nDST: %d\n", year, month, day, isDST);
    // printf("Sunrise: %s\nSunset: %s\n", expectedSunrise, expectedSunset);
    testSunTimes(cityName, latitude, longitude, year, month, day, timezone, isDST, expectedSunrise, expectedSunset);
    return 0;
}

// 将角度转换为弧度
double toRadians(double degree) {
    return degree * PI / 180.0;
}

// 将弧度转换为角度
double toDegrees(double radians) {
    return radians * 180.0 / PI;
}

// 计算儒略日
double calculateJulianDay(int year, int month, int day) {
    if (month <= 2) {
        year -= 1;
        month += 12;
    }
    int A = year / 100;
    int B = 2 - A + (A / 4);
    return (int)(365.25 * (year + 4716)) + (int)(30.6001 * (month + 1)) + day + B - 1524.5;
}

// 计算太阳正午时间
double calculateSolarNoon(double longitude, double julianDay, double timezone) {
    double n = julianDay - 2451545.0;
    double J_star = n - longitude / 360.0;
    double M = fmod(357.5291 + 0.98560028 * J_star, 360.0);
    double C = 1.9148 * sin(toRadians(M)) + 0.0200 * sin(toRadians(2 * M)) + 0.0003 * sin(toRadians(3 * M));
    double lambda = fmod(M + C + 180 + 102.9372, 360.0);
    double J_transit = 2451545.0 + J_star + 0.0053 * sin(toRadians(M)) - 0.0069 * sin(toRadians(2 * lambda));
    return fmod(J_transit - 2451545.0, 1.0) * 24.0 + timezone;
}

// 计算时角
double calculateHourAngle(double latitude, double declination) {
    double latRad = toRadians(latitude);
    double decRad = toRadians(declination);
    double cosH = (cos(toRadians(90.833)) - sin(latRad) * sin(decRad)) / (cos(latRad) * cos(decRad));
    return toDegrees(acos(cosH));
}

// 计算日出和日落时间
void calculateSunriseSunset(const char* cityName, double latitude, double longitude, int year, int month, int day, double timezone,int isDST, char* expectedSunrise, char* expectedSunset) {
    double julianDay = calculateJulianDay(year, month, day);
    double solarNoon = calculateSolarNoon(longitude, julianDay, timezone);
    double n = julianDay - 2451545.0;
    double M = fmod(357.5291 + 0.98560028 * n, 360.0);
    double C = 1.9148 * sin(toRadians(M)) + 0.0200 * sin(toRadians(2 * M)) + 0.0003 * sin(toRadians(3 * M));
    double lambda = fmod(M + C + 180 + 102.9372, 360.0);
    double declination = toDegrees(asin(sin(toRadians(lambda)) * sin(toRadians(23.44))));
    double hourAngle = calculateHourAngle(latitude, declination);

    double sunrise = solarNoon - hourAngle / 15.0;
    double sunset = solarNoon + hourAngle / 15.0;
    
    // if (isDST) {
    //     sunrise -= 1.0;
    //     sunset -= 1.0;
    // }
    // 格式化输出时间
    int sunriseHour = (int)sunrise;
    int sunriseMinute = (int)((sunrise - sunriseHour) * 60);
    int sunsetHour = (int)sunset;
    int sunsetMinute = (int)((sunset - sunsetHour) * 60);

    char calculatedSunrise[6];
    char calculatedSunset[6];

    snprintf(calculatedSunrise, sizeof(calculatedSunrise), "%02d:%02d", sunriseHour, sunriseMinute);
    snprintf(calculatedSunset, sizeof(calculatedSunset), "%02d:%02d", sunsetHour, sunsetMinute);

    // printf("计算的日出时间: %s, 预期的日出时间: %s\n", calculatedSunrise, expectedSunrise);
    // printf("计算的日落时间: %s, 预期的日落时间: %s\n", calculatedSunset, expectedSunset);

    // 计算差值
    int calcSunriseMinutes = sunriseHour * 60 + sunriseMinute;
    int expectedSunriseHour, expectedSunriseMinute;
    sscanf(expectedSunrise, "%d:%d", &expectedSunriseHour, &expectedSunriseMinute);
    int expectedSunriseMinutes = expectedSunriseHour * 60 + expectedSunriseMinute;
    int sunriseDifference = calcSunriseMinutes - expectedSunriseMinutes;

    int calcSunsetMinutes = sunsetHour * 60 + sunsetMinute;
    int expectedSunsetHour, expectedSunsetMinute;
    sscanf(expectedSunset, "%d:%d", &expectedSunsetHour, &expectedSunsetMinute);
    int expectedSunsetMinutes = expectedSunsetHour * 60 + expectedSunsetMinute;
    int sunsetDifference = calcSunsetMinutes - expectedSunsetMinutes;

    // printf("日出时间差值为: %d 分钟\n", sunriseDifference);
    // printf("日落时间差值为: %d 分钟\n", sunsetDifference);

    // printf("测试城市：%s\n", cityName);
    // printf("日期: %04d-%02d-%02d\n", year, month, day);
    // 根据格式进行打印
    printf("%-20s | %04d-%02d-%02d | %s | %s | %d | %s | %s | %d |\n",
             cityName, year, month, day, calculatedSunrise, expectedSunrise, sunriseDifference,
             calculatedSunset, expectedSunset, sunsetDifference);
    // if (strcmp(calculatedSunrise, expectedSunrise) == 0 && strcmp(calculatedSunset, expectedSunset) == 0) {
    //     printf("结果一致\n");
    // } else {
    //     printf("结果不一致\n");
    // }
}
